﻿using Furion;
using Furion.DatabaseAccessor;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Impl.Triggers;
using Queer.AutoJob.Core.Entity;
using Queer.Enum;
using Queer.Util;
using Queer.Util.Helper;
using Queer.Util.Model;
using System;
using System.Threading.Tasks;

namespace Queer.AutoJob
{
    public class JobExecute : IJob
    {
        /// <summary>
        /// 执行操作
        /// </summary>
        public Task Execute(IJobExecutionContext context)
        {
            return Task.Run(async () =>
            {
                TData obj = new TData();
                AutoJobEntity dbJobEntity = null;

                var serviceScopeFactory = App.GetService<IServiceScopeFactory>();

                using (var scope = serviceScopeFactory.CreateScope())
                {
                    var services = scope.ServiceProvider;
                    var repository = Db.GetRepository<AutoJobEntity>(services);

                    #region 任务执行

                    try
                    {
                        JobDataMap jobData = context.JobDetail.JobDataMap;
                        long jobId = jobData["Id"].ParseToLong();

                        // 获取数据库中的任务
                        dbJobEntity = repository.Find(jobId);

                        if (dbJobEntity != null && dbJobEntity.JobStatus == StatusEnum.Yes.ParseToInt())
                        {
                            CronTriggerImpl trigger = context.Trigger as CronTriggerImpl;
                            if (trigger != null)
                            {
                                if (trigger.CronExpressionString != dbJobEntity.CronExpression)
                                {
                                    // 更新任务周期
                                    trigger.CronExpressionString = dbJobEntity.CronExpression;
                                    await JobScheduler.GetScheduler().RescheduleJob(trigger.Key, trigger);
                                }

                                // 执行任务
                                switch (context.JobDetail.Key.Name)
                                {
                                    case "数据库备份":
                                        obj = await services.GetService<DatabasesBackupJob>().Start();
                                        break;

                                    default:
                                        obj.Message = "未找到匹配名称的任务，任务名称：" + context.JobDetail.Key.Name;
                                        break;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        obj.Message = ex.GetOriginalException().Message;
                        LogHelper.Error(ex);
                    }

                    #endregion

                    #region 更新日志

                    if (dbJobEntity == null && dbJobEntity.JobStatus != StatusEnum.Yes.ParseToInt())
                        return;

                    // 更新下次运行时间
                    string sql = "update SysAutoJob set NextStartTime=@NextStartTime where Id=@Id";
                    repository.SqlNonQuery(sql, new { Id = dbJobEntity.Id.GetValueOrDefault(), NextStartTime = context.NextFireTimeUtc.Value.DateTime.AddHours(8) });

                    // 记录执行状态（状态为3的返回信息不记录日志
                    if (obj.Tag == 3)
                        return;

                    var jobLog = new AutoJobLogEntity
                    {
                        Id = IdGeneratorHelper.Instance.GetId(),
                        JobGroupName = context.JobDetail.Key.Group,
                        JobName = context.JobDetail.Key.Name,
                        LogStatus = obj.Tag,
                        Remark = obj.Message,
                        BaseCreateTime = DateTime.Now
                    };

                    sql = @"insert into SysAutoJobLog(Id,BaseCreateTime,JobGroupName,JobName,LogStatus,Remark)
                                              values(@Id, @BaseCreateTime, @JobGroupName, @JobName, @LogStatus, @Remark)";
                    repository.SqlNonQuery(sql, jobLog);

                    #endregion

                }
            });
        }
    }
}